package learn.java.basic.net;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;


@Slf4j
public class LocalSocketServer implements LocalServer {

    private ServerSocket serverSocket;
    private final Object lock = new Object();

    private ExecutorService executorService = Executors.newWorkStealingPool();

    private ConcurrentLinkedQueue<FutureTask> taskQueue = new ConcurrentLinkedQueue<>();

    @Override
    public void start() {
        synchronized (lock) {
            if (serverSocket == null) {
                try {
                    serverSocket = new ServerSocket();
                    InetAddress localHost = InetAddress.getLocalHost();
                    InetAddress address = InetAddress.getLocalHost();

                    System.out.println("计算机名" + address.getHostName());

                    System.out.println("IP地址" + address.getHostAddress());

                    byte[] bytes = address.getAddress();//获取字节数组形式的IP地址  

                    System.out.println("字节数组形式的Ip" + Arrays.toString(bytes));
                    InetSocketAddress inetSocketAddress = new InetSocketAddress(localHost, 8080);
                    serverSocket.bind(inetSocketAddress);
                    dealTask();
                    while (true) {
                        Socket socket = serverSocket.accept();
                        FutureTask task = createTask(socket);
                        taskQueue.add(task);
                        executorService.submit(task);
                        log.info("新增task:");
                    }

                } catch (IOException e) {
                    log.error("启动异常：【{}】", e);
                }

            }
        }
    }

    public void dealTask() {
        executorService.submit(() -> {
            while (true) {
                FutureTask<String> futureTask = taskQueue.poll();
                if (futureTask.isDone()) {
                    log.info("task执行完成：{}",futureTask.get());
                } else {
                    taskQueue.offer(futureTask);
                }
            }
        });
    }

    private FutureTask createTask(Socket socket) {
        return new FutureTask<>(new SocketCallable(socket));
    }

    class SocketCallable implements Callable<String> {

        private Socket socket;

        SocketCallable(Socket socket) {
            this.socket = socket;
        }

        @Override
        public String call() throws Exception {
            byte[] bytes = new byte[1204];
            BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
            StringBuilder stringBuffer = new StringBuilder();
            while (bufferedInputStream.read(bytes, 0, bytes.length) > 0) {
                stringBuffer.append(new String(bytes, StandardCharsets.UTF_8));
            }


            if (!socket.isClosed()) {
                socket.close();
            }
            Thread.sleep(Duration.ofSeconds(RandomUtils.nextInt(1, 5)).toMillis());
            return stringBuffer.toString();
        }
    }

    @Override
    public void stop() {
        try {
            serverSocket.close();
        } catch (IOException e) {
            log.error("{}", e);
        }
    }

    public static void main(String[] args) {
        new LocalSocketServer().start();
    }
}
